package com.yupi.apiinvokproviderdemo.controller;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yupi.apiinvokproviderdemo.mapper.UserMapper;
import com.yupi.apiinvokproviderdemo.model.dto.AccessModel;
import com.yupi.apiinvokproviderdemo.model.dto.ContentModel;
import com.yupi.apiinvokproviderdemo.model.dto.QueryUserRequest;
import com.yupi.apiinvokproviderdemo.model.entity.User;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * @author yanghaifeng
 * @date 2024/1/22 16:33
 */
@RequestMapping("/provider")
@RestController
public class ProviderController {

    private static final String ACCESSKEY = "yhf";
    private static final String SECRETKEY = "QAZ2wsx";

    @Resource
    private UserMapper userMapper;

    /**
     * 模拟注册
     *
     * @return
     */
    @GetMapping("/register")
    public AccessModel register(@RequestParam("username") String username, @RequestParam("password") String password) {
        // TODO: 2024/1/22 校验用户名和密码

        // TODO: 2024/1/22 保存用户

        // TODO: 2024/1/22 分配AccessKey和SecretKey
        AccessModel result = new AccessModel();
        result.setAccessKey(ACCESSKEY);
        result.setSecretKey(SECRETKEY);
        return result;
    }


    /**
     * 业务接口-扫描内容是否安全
     *
     * @return
     */
    @PostMapping("/check")
    public String check(@RequestBody ContentModel content, HttpServletRequest request) {
        // 从请求头中获取AccessKey和SecretKey
        String accessKey = request.getHeader("accessKey");
        String secretKey = request.getHeader("secretKey");
        if (!ACCESSKEY.equals(accessKey) || !SECRETKEY.equals(secretKey)) {
            return "无权限";
        }
        return "内容安全";
    }

    /**
     * 业务接口-扫描内容是否安全（凭证校验）
     *
     * @return
     */
    @PostMapping("/generateCertificateCheck")
    public String generateCertificateCheck(@RequestBody ContentModel content, HttpServletRequest request) {
        // 从请求头中获取AccessKey
        String accessKey = request.getHeader("accessKey");
        String certificate = request.getHeader("certificate");
        // TODO: 2024/1/22 从数据库中根据accessKey获取secretKey
        String secretKey = SECRETKEY;

        // 生成凭证
        String json = JSONUtil.toJsonStr(content);
        Digester md5 = new Digester(DigestAlgorithm.MD5);
        String encodeStr = json + secretKey;
        String digestHex = md5.digestHex(encodeStr);
        System.out.println("服务端生成的凭证:" + digestHex);
        System.out.println("客户端生成的凭证:" + certificate);

        // 对比凭证
        if (!digestHex.equals(certificate)) {
            return "无权限";
        }
        return "内容安全";
    }

    /**
     * 业务接口-扫描内容是否安全（凭证中加入时间戳校验）
     *
     * @return
     */
    @PostMapping("/generateCertificateTimestampCheck")
    public String generateCertificateTimestampCheck(@RequestBody ContentModel content, HttpServletRequest request) {
        // 从请求头中获取AccessKey
        String accessKey = request.getHeader("accessKey");
        String certificate = request.getHeader("certificate");
        String timestamp = request.getHeader("timestamp");
        // 校验时间戳是否在有效范围内
        if (StrUtil.isBlank(timestamp)) {
            return "时间戳未传递";
        }
        long aLong = Long.parseLong(timestamp);
        DateTime timestampDate = DateUtil.date(aLong);
        DateTime currentDateTime = DateTime.now();
        // 如果当前时间在客户端传递的时间戳时间之前则报错
        if (currentDateTime.isBefore(timestampDate)) {
            return "时间错误";
        }
        // 计算相差时间，5分钟之内允许接口访问
        long minute = DateUtil.between(timestampDate, currentDateTime, DateUnit.MINUTE);
        System.out.println("相差时间：" + minute);
        if (minute > 5) {
            return "相差时间超过5分钟";
        }

        // TODO: 2024/1/22 从数据库中根据accessKey获取secretKey
        String secretKey = SECRETKEY;

        // 生成凭证
        String json = JSONUtil.toJsonStr(content);
        Digester md5 = new Digester(DigestAlgorithm.MD5);
        String encodeStr = json + timestamp + secretKey;
        String digestHex = md5.digestHex(encodeStr);
        System.out.println("服务端生成的凭证:" + digestHex);
        System.out.println("客户端生成的凭证:" + certificate);

        // 对比凭证
        if (!digestHex.equals(certificate)) {
            return "无权限";
        }
        return "内容安全";
    }


    /**
     * 查询用户名字
     *
     * @return
     */
    @PostMapping("/queryUserName")
    public Object queryUserName(@RequestBody QueryUserRequest dto, HttpServletRequest request) {
        // 从请求头中获取AccessKey
        String accessKey = request.getHeader("accessKey");
        String certificate = request.getHeader("certificate");
        String timestamp = request.getHeader("timestamp");
        // 校验时间戳是否在有效范围内
        if (StrUtil.isBlank(timestamp)) {
            return "时间戳未传递";
        }
        long aLong = Long.parseLong(timestamp);
        DateTime timestampDate = DateUtil.date(aLong);
        DateTime currentDateTime = DateTime.now();
        // 如果当前时间在客户端传递的时间戳时间之前则报错
        if (currentDateTime.isBefore(timestampDate)) {
            return "时间错误";
        }
        // 计算相差时间，5分钟之内允许接口访问
        long minute = DateUtil.between(timestampDate, currentDateTime, DateUnit.MINUTE);
        System.out.println("相差时间：" + minute);
        if (minute > 5) {
            return "相差时间超过5分钟";
        }

        // 从数据库中根据accessKey获取secretKey
        User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
                .eq(User::getAccessKey, accessKey));
        String secretKey = user.getSecretKey();

        // 生成凭证
        String json = JSONUtil.toJsonStr(dto);
        Digester md5 = new Digester(DigestAlgorithm.MD5);
        String encodeStr = json + timestamp + secretKey;
        String digestHex = md5.digestHex(encodeStr);
        System.out.println("服务端生成的凭证:" + digestHex);
        System.out.println("客户端生成的凭证:" + certificate);

        // 对比凭证
        if (!digestHex.equals(certificate)) {
            return "无权限";
        }

        // 根据名称查询数据返回
        return userMapper.selectOne(Wrappers.lambdaQuery(User.class)
                .eq(User::getUserAccount, dto.getUserName()));
    }

    @GetMapping("/test")
    public Object test(@RequestParam("userId") Long userId) {
        System.out.println("test方法执行");
        return userMapper.selectById(userId);
    }
}
